unit View;

interface

uses Mathematic, Vector, GL, GLu;

type
  TOrthogonalView = class
  private
    aPosition: TVector;
    aWidth: TFloat;
    aHeight: TFloat;
    aRotation: TFloat;
    procedure SetWidth(paWidth: TFloat);
    procedure SetHeight(paHeight: TFloat);
  public
    constructor Create;overload;
    constructor Create(paPosition: TVector; paWidth, paHeight, paRotation: TFloat);overload;
    constructor CreateCopy(paView: TOrthogonalView);
    destructor Destroy;override;
    procedure Setup(Reset: Boolean);
    procedure GetWorldCoordinates(paX, paY, paWidth, paHeight: Integer; var paWorldX, paWorldY: TFloat);
    procedure DrawGrid(paSizeX, paSizeY: TFloat);
    property Position: TVector read aPosition write aPosition;
    property Width: TFloat read aWidth write SetWidth;
    property Height: TFloat read aHeight write SetHeight;
    property Rotation: TFloat read aRotation write aRotation;
  end;

implementation

procedure TOrthogonalView.SetWidth(paWidth: TFloat);
begin
    aWidth := paWidth;
    aHeight := (3.0 / 4.0) * paWidth;
end;

procedure TOrthogonalView.SetHeight(paHeight: TFloat);
begin
    aHeight := paHeight;
    aWidth := (4.0 / 3.0) * paHeight;
end;

constructor TOrthogonalView.Create;
begin
    inherited Create;
    aPosition := TVector.Create(0.0, 0.0, 0.0);
    aWidth := 1.0;
    aHeight := 3.0 / 4.0;
    aRotation := 0;
end;

constructor TOrthogonalView.Create(paPosition: TVector; paWidth, paHeight, paRotation: TFloat);
begin
    aPosition := TVector.CreateCopy(paPosition);
    aWidth := paWidth;
    aHeight := paHeight;
    aRotation := paRotation;
end;

constructor TOrthogonalView.CreateCopy(paView: TOrthogonalView);
begin
    aPosition := TVector.CreateCopy(paView.aPosition);
    aWidth := paView.aWidth;
    aHeight := paView.aHeight;
    aRotation := paView.aRotation;

end;

destructor TOrthogonalView.Destroy;
begin
    aPosition.Free;
    inherited Destroy;
end;

procedure TOrthogonalView.Setup(Reset: Boolean);
begin
    if Reset then begin
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity;
    end;
    glOrtho(aPosition.X - (aWidth / 2.0), aPosition.X + (aWidth / 2.0),
            aPosition.Y - (aHeight / 2.0), aPosition.Y + (aHeight / 2.0),
            aPosition.Z - 1.0, aPosition.Z + 1.0);
    glTranslated(aPosition.X, aPosition.Y, aPosition.Z);
    glRotated(aRotation, 0.0, 0.0, 1.0);
    glTranslated(-aPosition.X, -aPosition.Y, -aPosition.Z);
end;

procedure TOrthogonalView.GetWorldCoordinates(paX, paY, paWidth, paHeight: Integer; var paWorldX, paWorldY: TFloat);
var TempWorldX, TempWorldY, S, C: TFloat;
begin
    TempWorldX := paX - (paWidth / 2.0);
    TempWorldY := (paHeight / 2.0) - paY;
    S := Sin(DegToRad(aRotation));
    C := Cos(DegToRad(aRotation));
    paWorldX := TempWorldX * C + TempWorldY * S;
    paWorldY := TempWorldY * C - TempWorldX * S;
    paWorldX := paWorldX * (aWidth / paWidth);
    paWorldY := paWorldY * (aHeight / paHeight);
    paWorldX := paWorldX + aPosition.X;
    paWorldY := paWorldY + aPosition.Y;
end;

procedure TOrthogonalView.DrawGrid(paSizeX, paSizeY: TFloat);
var I: TFloat;
begin
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix;
    glTranslated(aPosition.X, aPosition.Y, 0.0);
    I := 0.0;
    while I <= aWidth do begin
        glColor4d(0.8, 0.8, 0.8, 0.0);
        glBegin(GL_LINES);
            glVertex3d( I,  aHeight, 0.0);
            glVertex3d( I, -aHeight, 0.0);
            glVertex3d(-I,  aHeight, 0.0);
            glVertex3d(-I, -aHeight, 0.0);

        glEnd;
        I := I + paSizeX;
    end;
    I := 0.0;
    while I <= aHeight do begin
        glColor4d(0.8, 0.8, 0.8, 0.0);
        glBegin(GL_LINES);
            glVertex3d( aWidth,  I, 0.0);
            glVertex3d(-aWidth,  I, 0.0);
            glVertex3d( aWidth, -I, 0.0);
            glVertex3d(-aWidth, -I, 0.0);
        glEnd;
        I := I + paSizeY;
    end;
    glPopMatrix;
end;

end.
